
#include <cstring>
#include <cstdlib>
#include "ObjString.h"
#include "ObjHeader.h"
#include "vm.h"
#include "utils.h"
#include "common.h"

// fnv-1a算法实现Hash字符串
uint32_t ObjString::HashString(const char *str, uint32_t length) {
    uint32_t hashCode = 2166136261, idx = 0;
    while (idx < length) {
        hashCode ^= str[idx];
        hashCode *= 16777619;
        idx++;
    }
    return hashCode;
}

// 为string计算哈希码并将值存储到string->hash
void ObjString::HashObjString(ObjString *objString) {
    objString->hashCode = ObjString::HashString(objString->value.start, objString->value.length);
}

ObjString *ObjString::NewObjString(VM *vm, const char *str, uint32_t length) {
    //length为0时str必为NULL length不为0时str不为NULL
    ASSERT(length == 0 || str != NULL, "str length don`t match str!");

    //+1是为了结尾的'\0'
    auto *objString = ALLOCATE_EXTRA(vm, ObjString, length + 1);

    if (objString != nullptr) {
        objString->objHeader = *new ObjHeader(vm, OT_STRING, vm->stringClass);
        objString->value.length = length;

        //支持空字符串: str为null,length为0
        //如果非空则复制其内容
        if (length > 0) {
            memcpy(objString->value.start, str, length);
        }
        objString->value.start[length] = '\0';
        HashObjString(objString);
    } else {
        MEM_ERROR("Allocating ObjString failed!");
    }
    return objString;
}

ObjString::ObjString(VM *vm, const char *str, uint32_t length) {
    //length为0时str必为NULL length不为0时str不为NULL
    ASSERT(length == 0 || str != NULL, "str length don`t match str!");

    //+1是为了结尾的'\0'
    auto *objString = ALLOCATE_EXTRA(vm, ObjString, length + 1);

    if (objString != nullptr) {
        objString->objHeader = *new ObjHeader(vm, OT_STRING, vm->stringClass);
        objString->value.length = length;

        //支持空字符串: str为null,length为0
        //如果非空则复制其内容
        if (length > 0) {
            memcpy(objString->value.start, str, length);
        }
        objString->value.start[length] = '\0';
        HashObjString(objString);
    } else {
        MEM_ERROR("Allocating ObjString failed!");
    }

    this->value = objString->value;
    this->objHeader = objString->objHeader;
    this->hashCode = objString->hashCode;

}
